/*
 Trabajo Practico 3 Ejercicio 4
 Servidor UDP
 Segunda Entrega

 - Integrantes:
        - Barrera, Lourdes              DNI: 33306634
        - Martinez, Guillermo   		DNI: 34510461
        - Reyes, Leandro                DNI: 34213699
        - Rodriguez, Lucas              DNI: 34265017
*/

#include "../defines.c"

// Handler que finaliza servidor
void finalizar(int);

// Funcion error
void error(char*);

// Socket
int fd;

int main(int cargs,char* vargs[])
{
	int sin_size,val=1,i,numbytes;
	char buf[TAM_MSJ],mensaje[TAM_MSJ]="";
	struct sockaddr_in sk_srv;
	struct sockaddr sk_cli;
	int skclisize=sizeof(sk_cli);
	pid_t pid;
    int puerto;
    char ip_srv[30];
	FILE* arch;
	
	if((arch = fopen("config/server_cfg","rt")) == NULL)
	{
		printf("No se puede leer configuración\n");
		exit(1);
	}
	
	fscanf(arch,"IP = %s\nPUERTO = %d",ip_srv,&puerto);
	
	// Para hacer demonio
	if ((pid = fork()) < 0)
		exit(EXIT_FAILURE);
		
	if (pid > 0)
		exit(EXIT_SUCCESS);
		
	umask(0);

	// Manejar la finalizacion
	signal(SIGUSR1,finalizar);
	signal(SIGINT,finalizar);
	signal(SIGTERM,finalizar);
	
	// Abrir socket para conexion de stream, si no puede muestra el error y sale
	if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
		error("Error en creación socket");

	// Define las propiedades del socket
	sk_srv.sin_family = AF_INET;
	sk_srv.sin_port = htons(puerto);
	sk_srv.sin_addr.s_addr = inet_addr(ip_srv);
	bzero(&(sk_srv.sin_zero),8);

	// Bind socket
	if(bind(fd,(struct sockaddr*)&sk_srv,sizeof(struct sockaddr))==-1)
		error("Error en bind");

	// Cerrar descriptores standard
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
	
	sin_size=sizeof(struct sockaddr_in);

	while(1)
	{
		strcpy(mensaje,"");

		// Recibir informacion del cliente
		if ((numbytes=recvfrom(fd,buf,TAM_MSJ,0,&sk_cli,&skclisize)) == -1)
			error("Error en recv");

		sleep(1);

		// Calculando la fecha
		timestamp(mensaje);

		// Calculando la  diferencia de fechas
		resta_timestamp(mensaje, buf);

		// Envia el mensaje al cliente
		if(sendto(fd,&mensaje,sizeof(mensaje),0,&sk_cli,skclisize)<0)
			error("Error en send");
	}
}

void finalizar(int signal)
{
	close(fd);
	exit(0);
}

void error(char *e)
{
	// Error Log
	FILE* arch = fopen("error_log","wt");
	fprintf(arch,"%s\n",e);
	
	close(fd);
	fcloseall();
	exit(1);
}
